Imports System
Imports System.Collections.Specialized
Imports System.IO
Imports System.Reflection
Imports System.Text
Imports System.Web

<Serializable()> _
Public Class ExceptionInfo

#Region "Properties"

	Friend BaseException As Exception = Nothing

	Public ID As String = String.Empty
	Public AssemblyPath As String = String.Empty
	Public AssemblyDate As String = String.Empty
	Public AssemblyVersion As String = String.Empty
	Public SystemDotNetVersion As String = String.Empty
	Public SystemDateTime As String = String.Empty
	Public SystemName As String = String.Empty
	Public SystemRAM As String = String.Empty
	Public SystemOS As String = String.Empty
	Public UserIP As String = String.Empty
	Public UserLanguage As String = String.Empty
	Public CustomMessage As String = String.Empty
	Public HTML As String = String.Empty

#End Region

#Region "Constructors"

	Public Sub New()

	End Sub

	Public Sub New(ByVal ex As Exception, ByVal strCustomMessage As String)

		CustomMessage = strCustomMessage

		BaseException = ex

		GetID()
		GetAssemblyInfo()
		GetSystemInfo()
		GetUserInfo()

		GetHTML()

	End Sub

#End Region

#Region "Get error details"

	Private Sub GetID()

		Dim strID As String

		strID = "Ex"
		strID &= "." & DateTime.Now.ToString("yyyy-MM-dd")
		strID &= "." & DateTime.Now.ToString("HH-mm-ss")
		strID &= "." & DateTime.Now.Millisecond.ToString("000")
		strID &= "." & New Random().Next(0, 100).ToString("000")

		ID = strID

	End Sub

	Private Sub GetAssemblyInfo()

		Dim objAssembly As Assembly = Assembly.GetEntryAssembly()

		If objAssembly Is Nothing Then
			objAssembly = Assembly.GetCallingAssembly()
		End If

		If Not objAssembly Is Nothing Then

			Try
				AssemblyPath = objAssembly.Location.ToString()
			Catch
				AssemblyPath = My.Resources.Messages.Undefined
			End Try

			Try
				AssemblyVersion = objAssembly.GetName().Version.ToString()
			Catch
				AssemblyVersion = My.Resources.Messages.Undefined
			End Try

			Try
				AssemblyDate = File.GetLastWriteTime(objAssembly.Location).ToString()
			Catch
				AssemblyDate = My.Resources.Messages.Undefined
			End Try

		End If

	End Sub

	Private Sub GetSystemInfo()

		SystemDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
		SystemDotNetVersion = Environment.Version.ToString()
		SystemName = Environment.MachineName

		SystemOS = SystemInfo.GetOS()
		SystemRAM = SystemInfo.GetRAM()

	End Sub

	Private Sub GetUserInfo()

		UserIP = UserInfo.GetUserIP()
		UserLanguage = UserInfo.GetUserLanguage()

	End Sub

	Friend Sub GetHTML()

		Dim objCollection As New NameValueCollection
		Dim objStringBuilder As New StringBuilder
		Dim objHttpContext As HttpContext
		Dim strUrl As String = String.Empty
		Dim strUrlReferrer As String = String.Empty
		Const strTabHeader As String = "<table border='0' width='99%' cellpadding='3' cellspacing='1'><tr><td colspan='2' style='font-size:13px;color:#FFFFFF;background-color:#333333'><b> @TITLE </b></td></tr></table>"

		objHttpContext = HttpContext.Current

		If Not objHttpContext Is Nothing Then

			If Utils.DataUtil.HasValue(objHttpContext.Request.Url.AbsolutePath) Then
				strUrl = HttpContext.Current.Request.Url.AbsolutePath.ToString()
			Else
				strUrl = My.Resources.Messages.Undefined
			End If

			If Utils.DataUtil.HasValue(objHttpContext.Request.UrlReferrer) Then
				strUrlReferrer = HttpContext.Current.Request.UrlReferrer.ToString()
			Else
				strUrlReferrer = My.Resources.Messages.Undefined
			End If

		End If

		objStringBuilder.Append("<html><style type='text/css'>")
		objStringBuilder.Append(" body {font:11px Verdana; color:#000000} ")
		objStringBuilder.Append(" td {font:11px Verdana; color:#000000} ")
		objStringBuilder.Append(" h3 {font-family:Verdana; color:#FF0000; padding-bottom:3px; margin-bottom:3px; margin-left: -1px} ")
		objStringBuilder.Append(" .errorinfo {border:1px solid #DDDDDD; padding:2px; margin-top:10px; width:99%} ")
		objStringBuilder.Append(" .stack {background:#FFFFCC; font:12px 'Lucida Console'; padding:6px; margin-top:2px} ")
		objStringBuilder.Append(" .copyright {font:bold 11px Verdana; color:#113355; padding:4px; border:1px solid #AAAAAA; background-color:#FAFAFA; } ")
		objStringBuilder.Append("</style><body>")
		objStringBuilder.Append("<h3>" & My.Resources.Messages.ErrorTerm & ": ")
		objStringBuilder.Append(Config.AppName)
		objStringBuilder.Append("</h3><hr align='left' width='99%' size='1' color='#AAAAAA' noshadow><br />")

		If Not String.IsNullOrEmpty(CustomMessage) Then
			objStringBuilder.Append("<p><h4>" & HttpUtility.HtmlEncode(CustomMessage) & "</h4></p>")
		End If

		Dim ex As Exception = BaseException
		objStringBuilder.Append(GetExceptionDetailsHtml(ex, False))

		ex = BaseException.InnerException

		While Not ex Is Nothing
			objStringBuilder.Append(GetExceptionDetailsHtml(ex, True))
			ex = ex.InnerException
		End While

		objCollection.Add(My.Resources.Messages.Path, AssemblyPath)
		objCollection.Add(My.Resources.Messages.Version, AssemblyVersion)
		objCollection.Add(My.Resources.Messages.DateModified, AssemblyDate)

		objStringBuilder.Append(strTabHeader.Replace("@TITLE", "Assembly"))
		objStringBuilder.Append(ParseCollection(objCollection))
		objStringBuilder.Append("<br /><br />")
		objCollection.Clear()

		objCollection.Add(My.Resources.Messages.Name, SystemName)
		objCollection.Add("OS", SystemOS)
		objCollection.Add("Framework", SystemDotNetVersion)
		objCollection.Add("RAM", SystemRAM)
		objCollection.Add(My.Resources.Messages.DateTime, SystemDateTime)

		objStringBuilder.Append(strTabHeader.Replace("@TITLE", My.Resources.Messages.SystemInfo))
		objStringBuilder.Append(ParseCollection(objCollection))
		objStringBuilder.Append("<br /><br />")
		objCollection.Clear()

		objCollection.Add("IP", UserIP)
		objCollection.Add(My.Resources.Messages.Language, UserLanguage)

		If Utils.AssemblyUtil.GetAppType = Utils.AppTypeEnum.AspNet AndAlso Not objHttpContext.Request Is Nothing Then
			objCollection.Add("User Agent", HttpContext.Current.Request.UserAgent.ToString())
		End If

		objStringBuilder.Append(strTabHeader.Replace("@TITLE", My.Resources.Messages.UserInfo))
		objStringBuilder.Append(ParseCollection(objCollection))
		objStringBuilder.Append("<br /><br />")
		objCollection.Clear()

		If Utils.AssemblyUtil.GetAppType = Utils.AppTypeEnum.AspNet AndAlso Not objHttpContext.Request Is Nothing Then

			objCollection.Add("URL", strUrl)
			objCollection.Add(My.Resources.Messages.UrlReferrer, strUrlReferrer)

			objStringBuilder.Append(strTabHeader.Replace("@TITLE", "Request"))
			objStringBuilder.Append(ParseCollection(objCollection))
			objStringBuilder.Append("<br /><br />")
			objCollection.Clear()

			objStringBuilder.Append(strTabHeader.Replace("@TITLE", "Request.QueryString"))
			objStringBuilder.Append(ParseCollection(HttpContext.Current.Request.QueryString))
			objStringBuilder.Append("<br /><br />")

			If HttpContext.Current.Request.Form.Count > 0 Then
				objStringBuilder.Append(strTabHeader.Replace("@TITLE", "Request.Form"))
				objStringBuilder.Append(ParseCollection(HttpContext.Current.Request.Form))
				objStringBuilder.Append("<br /><br />")
			End If

			If HttpContext.Current.Request.Cookies.Count > 0 Then
				objStringBuilder.Append(strTabHeader.Replace("@TITLE", "Cookies"))
				objStringBuilder.Append(ParseCollection(HttpContext.Current.Request.Cookies))
				objStringBuilder.Append("<br /><br />")
			End If

			Try
				If HttpContext.Current.Session Is Nothing AndAlso Not HttpContext.Current.Session.IsReadOnly Then
					objStringBuilder.Append(strTabHeader.Replace("@TITLE", "Session"))
					objStringBuilder.Append(ParseCollection(HttpContext.Current.Session))
					objStringBuilder.Append("<br /><br />")
				End If
			Catch
			End Try

		End If

		objStringBuilder.Append("<br />")
		objStringBuilder.Append("<b>" & My.Resources.Messages.ErrooReferenceNotice & "</b>")

		HTML = objStringBuilder.ToString()

	End Sub

	Private Function GetExceptionDetailsHtml(ByVal ex As Exception, ByVal inner As Boolean) As String

		Dim objStringBuilder As New StringBuilder

		objStringBuilder.Append("<div class='errorinfo'>")

		If inner Then
			objStringBuilder.Append("<b>" & My.Resources.Messages.InnerException & "</b><br /><br />")
		End If

		objStringBuilder.Append("<b>" & My.Resources.Messages.Type & ":</b> ")
		objStringBuilder.Append(HttpUtility.HtmlEncode(ex.GetType.FullName))
		objStringBuilder.Append("<br />")
		objStringBuilder.Append("<b>" & My.Resources.Messages.Message & ":</b> ")
		objStringBuilder.Append(HttpUtility.HtmlEncode(ex.Message))
		objStringBuilder.Append("<br />")
		objStringBuilder.Append("<b>" & My.Resources.Messages.Source & ":</b> ")
		objStringBuilder.Append(HttpUtility.HtmlEncode(ex.Source))
		objStringBuilder.Append("<br />")
		objStringBuilder.Append("<b>" & My.Resources.Messages.Method & ":</b> ")
		objStringBuilder.Append(HttpUtility.HtmlEncode(ex.TargetSite.Name))
		objStringBuilder.Append("<br /><br />")
		objStringBuilder.Append("<b>" & My.Resources.Messages.Details & ":</b> ")
		objStringBuilder.Append("<div class='stack'>")
		objStringBuilder.Append(HttpUtility.HtmlEncode(ex.StackTrace).Replace(Environment.NewLine, "<br />"))
		objStringBuilder.Append("</div></div><br />")

		Return objStringBuilder.ToString()

	End Function

#End Region

#Region "Parse collections"

	Private Function ParseCollection(ByVal objCookieCollection As HttpCookieCollection) As String

		Dim strReturn As String
		Dim strItem As String
		Dim objCollection As New NameValueCollection

		For Each strItem In objCookieCollection
			objCollection.Add(strItem, objCookieCollection(strItem).Value)
		Next strItem

		strReturn = ParseCollection(objCollection)
		objCollection.Clear()

		Return strReturn

	End Function

	Private Function ParseCollection(ByVal objSessionCollection As SessionState.HttpSessionState) As String

		Dim strReturn As String
		Dim strItem As String
		Dim objCollection As New NameValueCollection

		For Each strItem In objSessionCollection
			objCollection.Add(strItem, objSessionCollection(strItem).ToString())
		Next strItem

		strReturn = ParseCollection(objCollection)
		objCollection.Clear()

		Return strReturn

	End Function

	Private Function ParseCollection(ByVal objCollection As NameValueCollection) As String

		Dim objTableBuilder As New StringBuilder
		Dim intCount As Integer

		objTableBuilder.Append("<table width='99%' cellspacing='1' cellpadding='3'>")

		Try

			If Not objCollection Is Nothing AndAlso objCollection.Count > 0 Then

				objTableBuilder.Append("<tr align='top' bgcolor='#CACACA'>")
				objTableBuilder.Append("<td>")
				objTableBuilder.Append(My.Resources.Messages.Name)
				objTableBuilder.Append("</td><td>")
				objTableBuilder.Append(My.Resources.Messages.Value)
				objTableBuilder.Append("</td></tr>")
				objTableBuilder.Append(Environment.NewLine)

				intCount = objCollection.Count - 1

				For i As Integer = 0 To intCount

					Dim excluded As Boolean = False

					For k As Integer = 0 To Config.ExcludedCollectionKeywords.Length - 1
						If objCollection.Keys(i).ToLower().Contains(Config.ExcludedCollectionKeywords(k)) Then
							excluded = True
							Exit For
						End If
					Next

					objTableBuilder.Append("<tr align='top' bgcolor='")

					If i Mod 2 = 0 Then
						objTableBuilder.Append("#FCFCFC")
					Else
						objTableBuilder.Append("#F0F0F0")
					End If

					objTableBuilder.Append("'><td>")
					objTableBuilder.Append(HttpUtility.HtmlEncode(objCollection.Keys(i)))
					objTableBuilder.Append("</td><td>")

					If excluded Then
						objTableBuilder.Append("[[" & My.Resources.Messages.Hidden.ToUpper() & "]]")
					Else
						objTableBuilder.Append(HttpUtility.HtmlEncode(objCollection(i)))
					End If

					objTableBuilder.Append("</td></tr>")
					objTableBuilder.Append(Environment.NewLine)

				Next i

			Else

				objTableBuilder.Append("<tr align='top' bgcolor='FCFCFC'><td>")
				objTableBuilder.Append(My.Resources.Messages.EmptyCollection)
				objTableBuilder.Append("...</td></tr>")

			End If

		Catch ex As Exception

			Return ex.ToString()

		End Try

		objTableBuilder.Append("</table>")

		Return objTableBuilder.ToString()

	End Function

#End Region

End Class
